#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>

#include "slowcat.h"

struct job_st {
	int cps;
	int token;
	int burst;
	int pos;
};

typedef void (*sighandler_t)(int);

static struct job_st *jobs[JOB_MAX];
static int inited = 0;
static sighandler_t alrm_handler_save;

static void alrm_handler(int s)
{
	// 对各个令牌进行累加
	alarm(1);
	for (int i = 0; i < JOB_MAX; i++) {
		if(jobs[i] != NULL)
		{
			jobs[i]->token += jobs[i]->cps;
			if(jobs[i]->token > jobs[i]->burst)
			{
			 	jobs[i]->token = jobs[i]->burst;	
			}
		}
	}
}

static void module_unload(void)
{
	// 恢复现场
	signal(SIGALRM,alrm_handler_save);
	alarm(0);
	for (int i = 0; i < JOB_MAX; i++) {
		free(jobs[i]);
	}
}

static void module_load(void)
{
	alrm_handler_save = signal(SIGALRM, alrm_handler);
	alarm(1);
	// 钩子函数，卸载当前模块
	atexit(module_unload);
}

static int get_free_pos()
{
	for (int i = 0; i < JOB_MAX; i++) {
		if(jobs[i] == NULL)
		{
			return i;
		}
	}
	return -1;
}

job_t *job_init(int cps, int burst)
{
	struct job_st *me;
	int pos;
	if(!inited)
	{
		module_load();
		inited = 1;
	}

	pos = get_free_pos();
	if(pos < 0)
	{
		return NULL;
	}

	me = malloc(sizeof(*me));
	if(me == NULL)
	{
		return NULL;
	}

	me->token = 0;
	me->burst = burst;
	me->cps = cps;
	me->pos = pos;

	jobs[pos] = me;

	return me;
}

/*
 *获取令牌
 * */
int job_fetchtoken(job_t *job, int size)
{
	struct job_st *ptr = job;

	if(size <= 0)
	{
		return -EINVAL;
	}

	while(ptr->token <= 0)
	{
		pause();
	}
	
	int n = (ptr->token > size ? size : ptr->token);
	ptr->token -= n;

	return n;
}

/*
 * 存放令牌
 * */
int job_returntoken(job_t *ptr, int size)
{
	struct job_st *me = ptr;
	if(size <= 0)
	{
		return -EINVAL;
	}
	me->token += size;
	if(me->token > me->burst)
	{
		me->token = me->burst;
	}
	return -1;
}

int job_destory(job_t *ptr)
{
	struct job_st *me = ptr;
	jobs[me->pos] = NULL;
	free(ptr);
	return 0;
}

